package com.atguigu.gulimall.product.service.impl;

import com.atguigu.common.to.SkuReductionTO;
import com.atguigu.common.to.SpuBoundTo;
import com.atguigu.common.utils.PageUtils;
import com.atguigu.common.utils.Query;
import com.atguigu.common.utils.R;
import com.atguigu.gulimall.product.entity.*;
import com.atguigu.gulimall.product.dao.SpuInfoDao;
import com.atguigu.gulimall.product.feign.CouponFeignService;
import com.atguigu.gulimall.product.service.*;
import com.atguigu.gulimall.product.vo.*;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


@Service("spuInfoService")
public class SpuInfoServiceImpl extends ServiceImpl<SpuInfoDao, SpuInfoEntity> implements SpuInfoService {

	@Autowired
	private SpuInfoDescService spuInfoDescService;

	@Autowired
	private SpuImagesService spuImagesService;

	@Autowired
	private IPmsAttrService attrService;

	@Autowired
	private ProductAttrValueService productAttrValueService;

	@Autowired
	private SkuInfoService skuInfoService;

	@Autowired
	private SkuImagesService skuImagesService;

	@Autowired
	private SkuSaleAttrValueService skuSaleAttrValueService;

	@Autowired
	private CouponFeignService couponFeignService;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<SpuInfoEntity> page = this.page(
                new Query<SpuInfoEntity>().getPage(params),
                new QueryWrapper<SpuInfoEntity>()
        );

        return new PageUtils(page);
    }

    /**
     * todo 注意 大保存的debug
     * 注意在这个大保存过程中，因为开启了事务，所以在保存过程中的任何一步，出现异常，都会进行回滚
     * 数据库执行：set session transaction isolation level read uncommitted
     * 让数据库在这个回话的级别最低。
     * */
    @Transactional
	@Override
	public void saveSpuInfo(SpuSaveVo vo) {
		// 1-保存spu基本信息 pms_spu_info
		SpuInfoEntity infoEntity = new SpuInfoEntity();
		BeanUtils.copyProperties(vo,infoEntity);
		infoEntity.setCreateTime(new Date());
		infoEntity.setUpdateTime(new Date());
		this.saveBaseSpuInfo(infoEntity);
		// 2-保存spu的描述图片 pms_spu_info_desc
		SpuInfoDescEntity infoDescEntity = new SpuInfoDescEntity();
		List<String> decript = vo.getDecript();
		infoDescEntity.setSpuId(infoEntity.getId());
		infoDescEntity.setDecript(String.join(",",decript));
		spuInfoDescService.saveSpuInfoDesc(infoDescEntity);
		// 3-保存spu的图片集 pms_spu_images
		List<String> images = vo.getImages();
		spuImagesService.saveImages(infoEntity.getId(),images);
		// 4- 保存spu的规格参数 pms_product_attr_value
		List<BaseAttrs> baseAttrs = vo.getBaseAttrs();
		List<ProductAttrValueEntity> productAttrValueEntities = baseAttrs.stream().map(attr -> {
			// 将其收集成  pms_product_attr_value 表实体
			ProductAttrValueEntity valueEntity = new ProductAttrValueEntity();
			valueEntity.setAttrId(attr.getAttrId());
			// 查找属性名称,并设置
			PmsAttr attrEntity = attrService.getById(attr.getAttrId());
			valueEntity.setAttrName(attrEntity.getAttrName());
			valueEntity.setAttrValue(attr.getAttrValues());
			valueEntity.setQuickShow(attr.getShowDesc());
			valueEntity.setSpuId(infoEntity.getId());
			return valueEntity;
		}).collect(Collectors.toList());
		productAttrValueService.saveProductAttr(productAttrValueEntities);
		// 5-保存spu的积分信息， 垮库 sms_spu_bounds
		Bounds bounds = vo.getBounds();
		SpuBoundTo spuBoundTo = new SpuBoundTo();
		BeanUtils.copyProperties(bounds,spuBoundTo);
		spuBoundTo.setSpuId(infoEntity.getId());
		R r = couponFeignService.saveSpuBounds(spuBoundTo);
		if (r.getCode() != 0){
			log.error("远程保存sku积分信息失败");
		}

		// 6- 保存当前spu对应的所有sku信息
		// 6.1 - sku的基本信息 pms_sku_info
		List<Skus> skus = vo.getSkus();
		if (skus !=null && skus.size()>0){
			// 拿到skus 下图片list的默认图片。所以需要两次循环
			skus.forEach(item->{
				String defaultImg = "";
				for (Images image : item.getImages()) {
					// skus 实体的成员变量 images 封装的是 image 实体。有点疯狂套娃的意思
					if (image.getDefaultImg() ==1){
						defaultImg = image.getImgUrl();
					}
				}
				SkuInfoEntity skuInfoEntity = new SkuInfoEntity();
				// 想进行属性copy
				BeanUtils.copyProperties(item,skuInfoEntity);
				// 没有的自己再设置上
				skuInfoEntity.setBrandId(infoEntity.getBrandId());
				skuInfoEntity.setCatalogId(infoEntity.getCatalogId());
				skuInfoEntity.setSaleCount(0L);
				skuInfoEntity.setSpuId(infoEntity.getId());
				skuInfoEntity.setSkuDefaultImg(defaultImg);
				// 调用service方法保存  6.1 - sku的基本信息 pms_sku_info
				skuInfoService.saveSkuInfo(skuInfoEntity);
				Long skuId = skuInfoEntity.getSkuId();

				// 因为下面还有处理图片，所以先收集成list，之后再进行处理
				List<SkuImagesEntity> imagesEntities = item.getImages().stream().map(img -> {
					SkuImagesEntity skuImagesEntity = new SkuImagesEntity();

					skuImagesEntity.setSkuId(skuId);
					skuImagesEntity.setImgUrl(img.getImgUrl());
					skuImagesEntity.setDefaultImg(img.getDefaultImg());

					return skuImagesEntity;
				}).filter(entity->{
					// 不为空返回true就是需要，否则，剔除掉
					return StringUtils.isNotBlank(entity.getImgUrl());
				}).collect(Collectors.toList());

				// 6.2 sku的图片信息， pms_sku_images
				// todo 没有图片路径的无需保存
				skuImagesService.saveBatch(imagesEntities);
				// 6.3-sku的销售属性信息 pms_sku_sale_attr_value
				List<Attr> attrList = item.getAttr();
				List<SkuSaleAttrValueEntity> skuSaleAttrValueEntities = attrList.stream().map(attr -> {
					SkuSaleAttrValueEntity skuSaleAttrValueEntity = new SkuSaleAttrValueEntity();
					BeanUtils.copyProperties(attr, skuSaleAttrValueEntity);
					skuSaleAttrValueEntity.setSkuId(skuId);

					return skuSaleAttrValueEntity;
				}).collect(Collectors.toList());
				skuSaleAttrValueService.saveBatch(skuSaleAttrValueEntities);
				// 6.4 sku的的优惠，满减等相关信息。 sms_sku_ladder 以及 sms_sku_full_reduction 表中
				SkuReductionTO skuReductionTO = new SkuReductionTO();
				BeanUtils.copyProperties(item,skuReductionTO);
				skuReductionTO.setSkuId(skuId);
				// 剔除掉，打折，优惠为0元的无意义的记录
				if (skuReductionTO.getFullCount()>0 || skuReductionTO.getFullPrice().compareTo(new BigDecimal(0) )==1){
					R r1 = couponFeignService.saveSkuReduction(skuReductionTO);
					if (r1.getCode() !=0){
						log.error("远程保存sku 优惠信息失败");
					}
				}

			});


		}


	}

	@Override
	public void saveBaseSpuInfo(SpuInfoEntity infoEntity) {
		this.baseMapper.insert(infoEntity);
	}

	@Override
	public PageUtils queryPageByCondition(Map<String, Object> params) {
		QueryWrapper<SpuInfoEntity> queryWrapper = new QueryWrapper<>();
		String key = (String) params.get("key");

		if (StringUtils.isNotBlank(key)){
			queryWrapper.and(w->{
				w.eq("id",key).or().like("spu_name",key);
			});
		}
		String status = (String) params.get("status");
		if (StringUtils.isNotBlank(status)){
			queryWrapper.eq("publish_status",status);
		}
		String brandId = (String) params.get("brandId");
		if (StringUtils.isNotBlank(brandId)){
			queryWrapper.eq("brand_id",brandId);
		}
		String catelogId = (String) params.get("catelogId");
		if(!StringUtils.isEmpty(catelogId)&&!"0".equalsIgnoreCase(catelogId)){
			queryWrapper.eq("catalog_id",catelogId);
		}
		IPage<SpuInfoEntity> page = this.page(
				new Query<SpuInfoEntity>().getPage(params),
				queryWrapper
		);

		return new PageUtils(page);
	}


}